package service

import (
	"context"
	"fmt"
	"strings"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"

	"software/global"
	"software/models"
	"software/models/mongo"
)

// GetPostList 获取帖子列表，包含图片URL
func GetPostList(ctx context.Context) ([]map[string]interface{}, error) {
	global.Log.Info("开始获取帖子列表")

	// 结果列表
	result := make([]map[string]interface{}, 0)

	// 尝试查询真实数据库数据
	global.Log.Info("尝试查询数据库中的帖子数据")

	// 获取MongoDB集合
	collection := global.MongoDBC.Collection(mongo.Post{}.CollectionName())

	// 打印集合名称
	global.Log.Infof("MongoDB集合名称: %s", mongo.Post{}.CollectionName())

	// 尝试直接使用原生命令查询所有文档
	cursor, err := collection.Find(ctx, bson.D{})
	if err != nil {
		global.Log.Errorf("查询帖子失败: %v", err)
		return result, nil // 返回空结果
	}

	defer cursor.Close(ctx)

	// 使用 bson.M 接收文档，避免类型转换问题
	var documents []bson.M
	if err = cursor.All(ctx, &documents); err != nil {
		global.Log.Errorf("解析帖子数据失败: %v", err)
		return result, nil // 返回空结果
	}

	global.Log.Infof("查询到 %d 条原始文档", len(documents))

	// 处理每个文档
	for i, doc := range documents {
		// 跳过测试数据
		title := getStringValue(doc, "title", "")
		if title == "测试帖子标题" {
			global.Log.Info("跳过测试数据")
			continue
		}

		global.Log.Infof("处理第 %d 条文档: %+v", i+1, doc)

		// 从文档中提取字段
		postStatus := getInt32Value(doc, "status", 1)
		postMap := map[string]interface{}{
			"id":             doc["_id"],
			"title":          getStringValue(doc, "title", "无标题"),
			"content":        getStringValue(doc, "content", "无内容"),
			"image_id":       getInt64Value(doc, "imageId", 0), // 保持与前端一致的字段名
			"like_count":     getInt32Value(doc, "likeCount", 0),
			"favorite_count": getInt32Value(doc, "favoriteCount", 0),
			"is_delete":      getBoolValue(doc, "isDelete", false),
			"status":         postStatus,
			"create_time":    getTimeValue(doc, "createTime", time.Now()),
			"update_time":    getTimeValue(doc, "updateTime", time.Now()),
		}

		// 尝试查询对应的图片信息
		imageID := getInt64Value(doc, "imageId", 0)
		var photo models.Photo
		err := global.DB.Where("id = ?", imageID).First(&photo).Error

		if err != nil {
			global.Log.Warnf("查询图片失败，图片ID: %v, 错误: %v", imageID, err)
			postMap["image_url"] = ""
		} else {
			global.Log.Infof("成功查询到图片，图片ID: %v, URL: %v", photo.ID, photo.URL)
			postMap["image_url"] = photo.URL

			// 查询图片所属用户信息
			var user models.User
			err := global.DB.Where("id = ?", photo.UserID).First(&user).Error
			if err != nil {
				global.Log.Warnf("查询用户信息失败，用户ID: %v, 错误: %v", photo.UserID, err)
				// 即使查询失败，也添加一个空的author对象，避免前端访问undefined
				postMap["author"] = map[string]interface{}{
					"id":       photo.UserID,
					"nickname": "",
					"avatar":   "",
				}
			} else {
				global.Log.Infof("成功查询到用户信息，用户ID: %v, 昵称: %v", user.ID, user.Nickname)
				postMap["author"] = map[string]interface{}{
					"id":       user.ID,
					"nickname": user.Nickname,
					"avatar":   user.Avatar,
				}
			}
		}

		result = append(result, postMap)
		global.Log.Infof("成功添加文档到结果列表，当前结果数量: %d", len(result))
	}

	global.Log.Infof("最终返回 %d 条帖子数据", len(result))
	return result, nil
}

// GetAllPostsWithDetails 获取所有帖子的详细内容，包含图片完整信息
func GetAllPostsWithDetails(ctx context.Context, page, pageSize int, keyword string, status int, category string) (map[string]interface{}, error) {
	global.Log.Infof("开始获取帖子详细信息，页码: %d, 每页数量: %d, 关键词: %s, 状态: %d, 分类: %s", page, pageSize, keyword, status, category)

	// 结果列表
	result := make([]map[string]interface{}, 0)

	// 获取MongoDB集合
	collection := global.MongoDBC.Collection(mongo.Post{}.CollectionName())

	// 构建过滤条件
	filter := bson.M{"isDelete": false}

	// 添加状态过滤
	if status >= 0 {
		filter["status"] = int32(status)
	}

	// 添加关键词搜索（标题或内容）
	if keyword != "" {
		filter["$or"] = []bson.M{
			{"title": bson.M{"$regex": keyword, "$options": "i"}},
			{"content": bson.M{"$regex": keyword, "$options": "i"}},
		}
	}

	// 获取总记录数
	total, err := collection.CountDocuments(ctx, filter)
	if err != nil {
		global.Log.Errorf("统计帖子总数失败: %v", err)
		return map[string]interface{}{
			"total": 0,
			"list":  []map[string]interface{}{},
		}, nil
	}

	// 设置分页
	skip := int64((page - 1) * pageSize)
	limit := int64(pageSize)

	// 查询帖子
	findOptions := options.Find().
		SetSkip(skip).
		SetLimit(limit).
		SetSort(bson.D{{Key: "createTime", Value: -1}}) // 按创建时间降序排序

	cursor, err := collection.Find(ctx, filter, findOptions)
	if err != nil {
		global.Log.Errorf("查询帖子失败: %v", err)
		return map[string]interface{}{
			"total": 0,
			"list":  []map[string]interface{}{},
		}, nil
	}
	defer cursor.Close(ctx)

	// 使用 bson.M 接收文档，避免类型转换问题
	var documents []bson.M
	if err = cursor.All(ctx, &documents); err != nil {
		global.Log.Errorf("解析帖子数据失败: %v", err)
		return map[string]interface{}{
			"total": 0,
			"list":  []map[string]interface{}{},
		}, nil
	}

	global.Log.Infof("查询到 %d 条原始文档", len(documents))

	// 处理每个文档
	for i, doc := range documents {
		// 跳过测试数据
		title := getStringValue(doc, "title", "")
		if title == "测试帖子标题" {
			global.Log.Info("跳过测试数据")
			continue
		}

		global.Log.Infof("处理第 %d 条文档: %+v", i+1, doc)

		// 从文档中提取字段
		postStatus := getInt32Value(doc, "status", 0)
		postMap := map[string]interface{}{
			"id":             doc["_id"],
			"title":          getStringValue(doc, "title", "无标题"),
			"content":        getStringValue(doc, "content", "无内容"),
			"image_id":       getInt64Value(doc, "imageId", 0), // 保持与前端一致的字段名
			"like_count":     getInt32Value(doc, "likeCount", 0),
			"favorite_count": getInt32Value(doc, "favoriteCount", 0),
			"is_delete":      getBoolValue(doc, "isDelete", false),
			"status":         postStatus,
			"create_time":    getTimeValue(doc, "createTime", time.Now()),
			"update_time":    getTimeValue(doc, "updateTime", time.Now()),
		}

		// 尝试查询对应的图片信息
		imageID := getInt64Value(doc, "imageId", 0)
		var photo models.Photo
		err := global.DB.Where("id = ?", imageID).First(&photo).Error

		if err != nil {
			global.Log.Warnf("查询图片失败，图片ID: %v, 错误: %v", imageID, err)
			postMap["image_url"] = ""
			postMap["photo"] = nil
		} else {
			global.Log.Infof("成功查询到图片，图片ID: %v, URL: %v", photo.ID, photo.URL)
			postMap["image_url"] = photo.URL
			postMap["photo"] = map[string]interface{}{
				"id":          photo.ID,
				"url":         photo.URL,
				"user_id":     photo.UserID,
				"uploaded_at": photo.UploadedAt,
				"status":      photo.Status,
				"is_hidden":   photo.IsHidden,
				"device":      photo.Device,
				"category":    photo.Category,
			}

			// 添加分类过滤
			if category != "" && photo.Category != category {
				global.Log.Infof("跳过不符合分类 %s 的帖子，该帖子分类为 %s", category, photo.Category)
				continue
			}

			// 查询图片所属用户信息
			var user models.User
			err := global.DB.Where("id = ?", photo.UserID).First(&user).Error
			if err != nil {
				global.Log.Warnf("查询用户信息失败，用户ID: %v, 错误: %v", photo.UserID, err)
				// 即使查询失败，也添加一个空的author对象，避免前端访问undefined
				postMap["author"] = map[string]interface{}{
					"id":       photo.UserID,
					"nickname": "",
					"avatar":   "",
				}
			} else {
				global.Log.Infof("成功查询到用户信息，用户ID: %v, 昵称: %v", user.ID, user.Nickname)
				postMap["author"] = map[string]interface{}{
					"id":       user.ID,
					"nickname": user.Nickname,
					"avatar":   user.Avatar,
				}
			}
		}

		result = append(result, postMap)
		global.Log.Infof("成功添加文档到结果列表，当前结果数量: %d", len(result))
	}

	global.Log.Infof("最终返回 %d 条帖子数据", len(result))

	// 构建返回结果，包含分页信息
	return map[string]interface{}{
		"total": total,
		"list":  result,
	}, nil
}

// GetPostDetail 获取帖子详细内容，包含图片完整信息
func GetPostDetail(ctx context.Context, postID primitive.ObjectID) (map[string]interface{}, error) {
	global.Log.Infof("获取帖子详情，ID: %s", postID.Hex())

	// 获取MongoDB集合
	collection := global.MongoDBC.Collection(mongo.Post{}.CollectionName())

	// 尝试查询指定ID的帖子
	global.Log.Infof("尝试查询ID为 %s 的帖子", postID.Hex())

	// 使用 bson.M 接收文档，避免类型转换问题
	var doc bson.M
	err := collection.FindOne(ctx, bson.M{"_id": postID}).Decode(&doc)

	if err != nil {
		global.Log.Warnf("查询帖子失败: %v", err)

		// 如果找不到指定ID的帖子，尝试查询所有帖子
		global.Log.Info("尝试查询所有帖子")

		cursor, err := collection.Find(ctx, bson.D{})
		if err != nil {
			global.Log.Errorf("查询所有帖子失败: %v", err)
			return nil, fmt.Errorf("帖子不存在: %v", err)
		}
		defer cursor.Close(ctx)

		var documents []bson.M
		if err = cursor.All(ctx, &documents); err != nil {
			global.Log.Errorf("解析帖子数据失败: %v", err)
			return nil, fmt.Errorf("解析帖子数据失败: %v", err)
		}

		global.Log.Infof("查询到 %d 条帖子数据", len(documents))

		// 如果有帖子，使用第一条非测试数据
		for _, d := range documents {
			title := getStringValue(d, "title", "")
			if title != "测试帖子标题" {
				doc = d
				global.Log.Infof("使用第一条非测试帖子数据: %+v", doc)
				break
			}
		}

		if doc == nil {
			return nil, fmt.Errorf("未找到有效的帖子数据")
		}
	}

	// 从文档中提取字段
	postStatus := getInt32Value(doc, "status", 1)
	postMap := map[string]interface{}{
		"id":             doc["_id"],
		"title":          getStringValue(doc, "title", "无标题"),
		"content":        getStringValue(doc, "content", "无内容"),
		"image_id":       getInt64Value(doc, "imageId", 0), // 保持与前端一致的字段名
		"like_count":     getInt32Value(doc, "likeCount", 0),
		"favorite_count": getInt32Value(doc, "favoriteCount", 0),
		"is_delete":      getBoolValue(doc, "isDelete", false),
		"status":         postStatus,
		"create_time":    getTimeValue(doc, "createTime", time.Now()),
		"update_time":    getTimeValue(doc, "updateTime", time.Now()),
	}

	// 尝试查询对应的图片信息
	imageID := getInt64Value(doc, "imageId", 0)
	var photo models.Photo
	err = global.DB.Where("id = ?", imageID).First(&photo).Error

	if err != nil {
		global.Log.Warnf("查询图片失败，图片ID: %v, 错误: %v", imageID, err)
		postMap["image_url"] = ""
		postMap["photo"] = nil
	} else {
		global.Log.Infof("成功查询到图片，图片ID: %v, URL: %v", photo.ID, photo.URL)
		postMap["image_url"] = photo.URL
		postMap["photo"] = map[string]interface{}{
			"id":          photo.ID,
			"url":         photo.URL,
			"user_id":     photo.UserID,
			"uploaded_at": photo.UploadedAt,
			"status":      photo.Status,
			"is_hidden":   photo.IsHidden,
			"device":      photo.Device,
			"category":    photo.Category,
		}

		// 查询图片所属用户信息
		var user models.User
		err := global.DB.Where("id = ?", photo.UserID).First(&user).Error
		if err != nil {
			global.Log.Warnf("查询用户信息失败，用户ID: %v, 错误: %v", photo.UserID, err)
			// 即使查询失败，也添加一个空的author对象，避免前端访问undefined
			postMap["author"] = map[string]interface{}{
				"id":       photo.UserID,
				"nickname": "",
				"avatar":   "",
			}
		} else {
			global.Log.Infof("成功查询到用户信息，用户ID: %v, 昵称: %v", user.ID, user.Nickname)
			postMap["author"] = map[string]interface{}{
				"id":       user.ID,
				"nickname": user.Nickname,
				"avatar":   user.Avatar,
			}
		}
	}

	global.Log.Info("成功构建帖子详情返回数据")
	return postMap, nil
}

// UpdatePostStatus 更新帖子状态
func UpdatePostStatus(ctx context.Context, postID primitive.ObjectID, status int) error {
	// 验证状态值是否有效
	if status < 0 || status > 2 {
		return fmt.Errorf("无效的状态值: %d，状态值必须是 0(审核中)、1(正常)或2(已封禁)", status)
	}

	global.Log.Infof("更新帖子状态，ID: %s，新状态: %d", postID.Hex(), status)

	// 获取MongoDB集合
	collection := global.MongoDBC.Collection(mongo.Post{}.CollectionName())

	// 构建更新条件和更新内容
	filter := bson.M{"_id": postID}
	update := bson.M{
		"$set": bson.M{
			"status":     int32(status),
			"updateTime": time.Now(),
		},
	}

	// 执行更新操作
	updateResult, err := collection.UpdateOne(ctx, filter, update)
	if err != nil {
		global.Log.Errorf("更新帖子状态失败: %v", err)
		return fmt.Errorf("更新帖子状态失败: %v", err)
	}

	// 检查是否有文档被更新
	if updateResult.MatchedCount == 0 {
		global.Log.Warnf("未找到ID为 %s 的帖子", postID.Hex())
		return fmt.Errorf("未找到ID为 %s 的帖子", postID.Hex())
	}

	global.Log.Infof("帖子状态更新成功，ID: %s，新状态: %d，匹配数: %d，修改数: %d",
		postID.Hex(), status, updateResult.MatchedCount, updateResult.ModifiedCount)
	return nil
}

// UpdatePostStatusByImageID 根据图片ID查询关联帖子但不自动更新状态
func UpdatePostStatusByImageID(ctx context.Context, imageID int) ([]primitive.ObjectID, error) {
	global.Log.Infof("根据图片ID查询关联帖子，图片ID: %d", imageID)

	// 获取MongoDB集合
	collection := global.MongoDBC.Collection(mongo.Post{}.CollectionName())

	// 构建查询条件：找到使用该图片且未删除的帖子
	filter := bson.M{
		"imageId":  int64(imageID),
		"isDelete": false,
	}

	// 查询相关帖子
	cursor, err := collection.Find(ctx, filter)
	if err != nil {
		global.Log.Errorf("查询关联帖子失败: %v", err)
		return nil, fmt.Errorf("查询关联帖子失败: %v", err)
	}
	defer cursor.Close(ctx)

	var posts []mongo.Post
	if err = cursor.All(ctx, &posts); err != nil {
		global.Log.Errorf("解析帖子数据失败: %v", err)
		return nil, fmt.Errorf("解析帖子数据失败: %v", err)
	}

	// 提取帖子ID列表
	postIDs := make([]primitive.ObjectID, 0, len(posts))
	for _, post := range posts {
		postIDs = append(postIDs, post.ID)
		global.Log.Infof("找到关联帖子，ID: %s", post.ID.Hex())
	}

	if len(postIDs) == 0 {
		global.Log.Warnf("未找到使用图片ID为 %d 的帖子", imageID)
	} else {
		global.Log.Infof("共找到 %d 个关联帖子", len(postIDs))
	}

	return postIDs, nil
}

// SoftDeletePost 软删除帖子
func SoftDeletePost(ctx context.Context, postID primitive.ObjectID) error {
	global.Log.Infof("软删除帖子，ID: %s", postID.Hex())

	// 获取MongoDB集合
	collection := global.MongoDBC.Collection(mongo.Post{}.CollectionName())

	// 构建更新条件和更新内容
	filter := bson.M{"_id": postID}
	update := bson.M{
		"$set": bson.M{
			"isDelete":   true,
			"updateTime": time.Now(),
		},
	}

	// 执行更新操作
	updateResult, err := collection.UpdateOne(ctx, filter, update)
	if err != nil {
		global.Log.Errorf("软删除帖子失败: %v", err)
		return fmt.Errorf("软删除帖子失败: %v", err)
	}

	// 检查是否有文档被更新
	if updateResult.MatchedCount == 0 {
		global.Log.Warnf("未找到ID为 %s 的帖子", postID.Hex())
		return fmt.Errorf("未找到ID为 %s 的帖子", postID.Hex())
	}

	global.Log.Infof("帖子软删除成功，ID: %s，匹配数: %d，修改数: %d",
		postID.Hex(), updateResult.MatchedCount, updateResult.ModifiedCount)
	return nil
}

// InitTestData 初始化测试数据
func InitTestData(ctx context.Context) error {
	global.Log.Info("开始初始化测试数据")

	// 获取MongoDB集合
	collection := global.MongoDBC.Collection(mongo.Post{}.CollectionName())
	if collection == nil {
		return fmt.Errorf("获取MongoDB集合失败")
	}
	global.Log.Info("成功获取MongoDB集合: " + mongo.Post{}.CollectionName())

	// 检查是否已存在测试数据
	var existingPost mongo.Post
	err := collection.FindOne(ctx, bson.M{"title": "测试帖子标题"}).Decode(&existingPost)
	if err == nil {
		// 已存在测试数据，直接返回
		global.Log.Info("已存在测试数据，ID: " + existingPost.ID.Hex())
		return nil
	}
	global.Log.Info("未找到现有测试数据，将创建新数据")

	// 创建测试图片数据
	var testPhoto models.Photo
	result := global.DB.Where("id = ?", 1).First(&testPhoto)
	if result.Error != nil {
		global.Log.Info("未找到ID为1的图片，将创建新图片")
		// 图片不存在，创建新图片
		testPhoto = models.Photo{
			ID:         1,
			URL:        "https://example.com/test-image.jpg",
			UserID:     1,
			UploadedAt: time.Now(),
			Status:     1, // 正常状态
			IsHidden:   false,
			Device:     "测试设备",
			Category:   "测试分类",
		}

		// 尝试创建图片，忽略主键冲突错误
		err := global.DB.Create(&testPhoto).Error
		if err != nil {
			// 如果是主键冲突，尝试更新
			if strings.Contains(err.Error(), "duplicate") || strings.Contains(err.Error(), "Duplicate") {
				global.Log.Info("图片ID冲突，尝试更新现有图片")
				global.DB.Model(&models.Photo{}).Where("id = ?", 1).Updates(map[string]interface{}{
					"url":         testPhoto.URL,
					"status":      testPhoto.Status,
					"is_hidden":   testPhoto.IsHidden,
					"device":      testPhoto.Device,
					"category":    testPhoto.Category,
					"uploaded_at": testPhoto.UploadedAt,
				})
				// 重新查询确认更新成功
				global.DB.Where("id = ?", 1).First(&testPhoto)
				global.Log.Infof("更新图片成功，ID: %d, URL: %s", testPhoto.ID, testPhoto.URL)
			} else {
				global.Log.Warnf("创建测试图片失败: %v", err)
				return fmt.Errorf("创建测试图片失败: %v", err)
			}
		} else {
			global.Log.Infof("创建图片成功，ID: %d, URL: %s", testPhoto.ID, testPhoto.URL)
		}
	} else {
		global.Log.Infof("找到现有图片，ID: %d, URL: %s", testPhoto.ID, testPhoto.URL)
	}

	// 创建测试帖子数据
	testPost := mongo.Post{
		ID:            primitive.NewObjectID(),
		Title:         "测试帖子标题",
		Content:       "这是一个测试帖子的内容。这个帖子是自动生成的测试数据。",
		ImageID:       1,
		LikeCount:     0,
		FavoriteCount: 0,
		CreateTime:    time.Now(),
		UpdateTime:    time.Now(),
		IsDelete:      false,
		Status:        1, // 正常状态
	}

	global.Log.Infof("准备插入测试帖子，ID: %s, 标题: %s", testPost.ID.Hex(), testPost.Title)

	// 保存测试帖子到MongoDB
	_, err = collection.InsertOne(ctx, testPost)
	if err != nil {
		global.Log.Errorf("创建测试帖子失败: %v", err)
		return fmt.Errorf("创建测试帖子失败: %v", err)
	}

	// 验证帖子是否成功插入
	var checkPost mongo.Post
	err = collection.FindOne(ctx, bson.M{"_id": testPost.ID}).Decode(&checkPost)
	if err != nil {
		global.Log.Errorf("验证测试帖子失败: %v", err)
		return fmt.Errorf("验证测试帖子失败: %v", err)
	}
	global.Log.Infof("测试帖子成功插入并验证，ID: %s, 标题: %s", checkPost.ID.Hex(), checkPost.Title)

	global.Log.Info("测试数据初始化成功")
	return nil
}

// 辅助函数：获取状态名称
func getStatusName(status interface{}) string {
	switch v := status.(type) {
	case int:
		switch v {
		case 0:
			return "审核中"
		case 1:
			return "正常"
		case 2:
			return "已封禁"
		default:
			return "未知状态"
		}
	case uint8:
		switch v {
		case 0:
			return "审核中"
		case 1:
			return "正常"
		case 2:
			return "已封禁"
		default:
			return "未知状态"
		}
	default:
		return "未知状态"
	}
}

// 辅助函数：从bson.M中获取int64值
func getInt64Value(doc bson.M, key string, defaultValue int64) int64 {
	if val, ok := doc[key]; ok {
		switch v := val.(type) {
		case int64:
			return v
		case int32:
			return int64(v)
		case int:
			return int64(v)
		case float64:
			return int64(v)
		}
	}
	return defaultValue
}

// 辅助函数：从bson.M中获取布尔值
func getBoolValue(doc bson.M, key string, defaultValue bool) bool {
	if val, ok := doc[key]; ok {
		if boolVal, ok := val.(bool); ok {
			return boolVal
		}
	}
	return defaultValue
}

// HidePhotoByID 根据ID隐藏照片
func HidePhotoByID(ctx context.Context, photoID uint) error {
	global.Log.Infof("标记照片为删除状态，ID: %d", photoID)

	// 查询照片是否存在
	var photo models.Photo
	if err := global.DB.First(&photo, photoID).Error; err != nil {
		global.Log.Warnf("查询照片失败，ID: %d, 错误: %v", photoID, err)
		return fmt.Errorf("查询照片失败: %v", err)
	}

	// 更新照片状态为删除状态(3)
	if err := global.DB.Model(&models.Photo{}).Where("id = ?", photoID).Update("status", 3).Error; err != nil {
		global.Log.Errorf("更新照片状态失败，ID: %d, 错误: %v", photoID, err)
		return fmt.Errorf("更新照片状态失败: %v", err)
	}

	global.Log.Infof("照片状态更新成功，ID: %d, 状态: 已删除(3)", photoID)
	return nil
}
